#include "target.h"
#include "padl_uart.h"
#include "padl_pincon.h"
#include "padl_vic.h"

#include "../config/phal_uart_config.h"
#include "phal_uart.h"


// *********************** DEFINITIONS *************************

#define UART_FROM_ID(id) \
	(id == phal_uart0_ID) ? padl_uart_UART0 :\
	(id == phal_uart1_ID) ? padl_uart_UART1 :\
	(id == phal_uart2_ID) ? padl_uart_UART2 :\
						   padl_uart_UART3


// *********************** PROTOTYPES **************************

void phal_uart0_interruptRoutine(void);
void phal_uart1_interruptRoutine(void);
void phal_uart2_interruptRoutine(void);
void phal_uart3_interruptRoutine(void);

////////////////////////////////////////////////////////////////
/// Uart 0 handlers											 ///
////////////////////////////////////////////////////////////////
#if (UART0_ENABLE == TRUE) && (UART0_ENABLE_DATA_TRANSMITTED_INTERRUPT == TRUE)
extern phal_uart_DATA_TRANSMITTED_HANDLER(UART0_DATA_TRANSMITTED_HANDLER, args);
#endif

#if (UART0_ENABLE == TRUE) && (UART0_ENABLE_DATA_RECEIVED_INTERRUPT == TRUE)
extern phal_uart_DATA_RECEIVED_HANDLER(UART0_DATA_RECEIVED_HANDLER, args);
#endif

#if (UART0_ENABLE == TRUE) && (UART0_ENABLE_RECEIVING_DATA_ERROR_INTERRUPT == TRUE)
extern phal_uart_RECEIVING_DATA_ERROR_HANDLER(UART0_RECEIVING_DATA_ERROR_HANDLER, args);
#endif

////////////////////////////////////////////////////////////////
/// Uart 1 handlers											 ///
////////////////////////////////////////////////////////////////
#if (UART1_ENABLE == TRUE) && (UART1_ENABLE_DATA_TRANSMITTED_INTERRUPT == TRUE)
extern phal_uart_DATA_TRANSMITTED_HANDLER(UART1_DATA_TRANSMITTED_HANDLER, args);
#endif

#if (UART1_ENABLE == TRUE) && (UART1_ENABLE_DATA_RECEIVED_INTERRUPT == TRUE)
extern phal_uart_DATA_RECEIVED_HANDLER(UART1_DATA_RECEIVED_HANDLER, args);
#endif

#if (UART1_ENABLE == TRUE) && (UART1_ENABLE_RECEIVING_DATA_ERROR_INTERRUPT == TRUE)
extern phal_uart_RECEIVING_DATA_ERROR_HANDLER(UART1_RECEIVING_DATA_ERROR_HANDLER, args);
#endif

////////////////////////////////////////////////////////////////
/// Uart 2 handlers											 ///
////////////////////////////////////////////////////////////////
#if (UART2_ENABLE == TRUE) && (UART2_ENABLE_DATA_TRANSMITTED_INTERRUPT == TRUE)
extern phal_uart_DATA_TRANSMITTED_HANDLER(UART2_DATA_TRANSMITTED_HANDLER, args);
#endif

#if (UART2_ENABLE == TRUE) && (UART2_ENABLE_DATA_RECEIVED_INTERRUPT == TRUE)
extern phal_uart_DATA_RECEIVED_HANDLER(UART2_DATA_RECEIVED_HANDLER, args);
#endif

#if (UART2_ENABLE == TRUE) && (UART2_ENABLE_RECEIVING_DATA_ERROR_INTERRUPT == TRUE)
extern phal_uart_RECEIVING_DATA_ERROR_HANDLER(UART2_RECEIVING_DATA_ERROR_HANDLER, args);
#endif

////////////////////////////////////////////////////////////////
/// Uart 3 handlers											 ///
////////////////////////////////////////////////////////////////
#if (UART3_ENABLE == TRUE) && (UART3_ENABLE_DATA_TRANSMITTED_INTERRUPT == TRUE)
extern phal_uart_DATA_TRANSMITTED_HANDLER(UART3_DATA_TRANSMITTED_HANDLER, args);
#endif

#if (UART3_ENABLE == TRUE) && (UART3_ENABLE_DATA_RECEIVED_INTERRUPT == TRUE)
extern phal_uart_DATA_RECEIVED_HANDLER(UART3_DATA_RECEIVED_HANDLER, args);
#endif

#if (UART3_ENABLE == TRUE) && (UART3_ENABLE_RECEIVING_DATA_ERROR_INTERRUPT == TRUE)
extern phal_uart_RECEIVING_DATA_ERROR_HANDLER(UART3_RECEIVING_DATA_ERROR_HANDLER, args);
#endif

// ******************** GLOBAL VARIABLES ***********************

// *************************** BODY ****************************

////////////////////////////////////////////////////////////////
/// Uart initialization										 ///
////////////////////////////////////////////////////////////////
static void init(
					padl_uart_UartType *uart,
					U8 dataLength,
					BOOL enableParityChecking,
					U8 parity,
					U8 stopBit,
					U8 fractionalBaudrateDivisor,
					U8 fractionalBaudrateMultiplier,
					U16 baudrateDivisor,
					U8 interruptPriority,
					U8 interruptSource,
					void (*interruptRoutine)(void)
				)
{
#if (UART0_ENABLE == TRUE)
	if(uart == padl_uart_UART0)
	{
		padl_pincon_CONFIG_RXD0();
		padl_pincon_CONFIG_TXD0();
	}
#endif
#if (UART1_ENABLE == TRUE)
	if(uart == padl_uart_UART1)
	{
		padl_pincon_CONFIG_RXD1();
		padl_pincon_CONFIG_TXD1();
	}
#endif
#if (UART2_ENABLE == TRUE)
	if(uart == padl_uart_UART2)
	{
		padl_pincon_CONFIG_RXD2();
		padl_pincon_CONFIG_TXD2();
	}
#endif
#if (UART3_ENABLE == TRUE)
	if(uart == padl_uart_UART3)
	{
		padl_pincon_CONFIG_RXD3();
		padl_pincon_CONFIG_TXD3();
	}
#endif

  	padl_uart_SET_DATA_LENGTH(uart, dataLength);
  	padl_uart_SET_ENABLE_PARITY(uart, enableParityChecking);
  	if(enableParityChecking == TRUE)
  	{
  		padl_uart_SET_PARITY(uart, parity);
	}
  	padl_uart_SET_STOP_BIT(uart, stopBit);
  	padl_uart_ENABLE_BAUDRATE_DLA(uart);
  	padl_uart_SET_FRACTIONAL_BAUDRATE_DIVISOR(uart, fractionalBaudrateDivisor);
  	padl_uart_SET_FRACTIONAL_BAUDRATE_MULTIPLIER(uart, fractionalBaudrateMultiplier);
  	padl_uart_SET_BAUDRATE_DIVISOR(uart, baudrateDivisor);
  	padl_uart_DISABLE_BAUDRATE_DLA(uart);

	if(UART0_ENABLE_INTERRUPT == TRUE)
	{
		padl_vic_INSTALL_IRQ(interruptSource, interruptRoutine, interruptPriority);
	}

	padl_uart_ENABLE_RDA_INTERRUPT(uart);
	padl_uart_ENABLE_THRE_INTERRUPT(uart);
	padl_uart_ENABLE_RLS_INTERRUPT(uart);
}

////////////////////////////////////////////////////////////////
/// All uarts initialization								 ///
////////////////////////////////////////////////////////////////
void phal_uart_init(void)
{
	// Uart 0 ---------------------------
#if (UART0_ENABLE == TRUE)
	init(
			padl_uart_UART0,
			UART0_DATA_LENGTH,
			UART0_ENABLE_PARITY_CHECKING,
#if UART0_ENABLE_PARITY_CHECKING == TRUE
			UART0_PARITY,
#else
			NULL,
#endif
			UART0_STOP_BIT,
			UART0_FRACTIONAL_BAUDRATE_DIVISOR,
			UART0_FRACTIONAL_BAUDRATE_MULTIPLIER,
			UART0_BAUDRATE_DIVISOR,
#if UART0_ENABLE_INTERRUPT == TRUE
			UART0_INTERRUPT_PRIORITY,
			UART0_INT,
			phal_uart0_interruptRoutine
#else
			NULL,
			NULL,
			NULL
#endif
		);
#endif

	// Uart 1 ---------------------------
#if (UART1_ENABLE == TRUE)
	init(
			padl_uart_UART1,
			UART1_DATA_LENGTH,
			UART1_ENABLE_PARITY_CHECKING,
			UART1_PARITY,
			UART1_STOP_BIT,
			UART1_FRACTIONAL_BAUDRATE_DIVISOR,
			UART1_FRACTIONAL_BAUDRATE_MULTIPLIER,
			UART1_BAUDRATE_DIVISOR,
			UART1_INTERRUPT_PRIORITY,
			UART1_INT,
			phal_uart1_interruptRoutine
		);
#endif

	// Uart 2 ---------------------------
#if (UART2_ENABLE == TRUE)
	init(
			padl_uart_UART2,
			UART2_DATA_LENGTH,
			UART2_ENABLE_PARITY_CHECKING,
#if UART2_ENABLE_PARITY_CHECKING == TRUE
			UART2_PARITY,
#else
			NULL,
#endif
			UART2_STOP_BIT,
			UART2_FRACTIONAL_BAUDRATE_DIVISOR,
			UART2_FRACTIONAL_BAUDRATE_MULTIPLIER,
			UART2_BAUDRATE_DIVISOR,
#if UART2_ENABLE_INTERRUPT == TRUE
			UART2_INTERRUPT_PRIORITY,
			UART2_INT,
			phal_uart2_interruptRoutine
#else
			NULL,
			NULL,
			NULL
#endif
		);
#endif

	// Uart 3 ---------------------------
#if (UART3_ENABLE == TRUE)
	init(
			padl_uart_UART3,
			UART3_DATA_LENGTH,
			UART3_ENABLE_PARITY_CHECKING,
#if UART3_ENABLE_PARITY_CHECKING == TRUE
			UART3_PARITY,
#else
			NULL,
#endif
			UART3_STOP_BIT,
			UART3_FRACTIONAL_BAUDRATE_DIVISOR,
			UART3_FRACTIONAL_BAUDRATE_MULTIPLIER,
			UART3_BAUDRATE_DIVISOR,
#if UART3_ENABLE_INTERRUPT == TRUE
			UART3_INTERRUPT_PRIORITY,
			UART3_INT,
			phal_uart3_interruptRoutine
#else
			NULL,
			NULL,
			NULL
#endif
		);
#endif
}

////////////////////////////////////////////////////////////////
/// Send byte												 ///
////////////////////////////////////////////////////////////////
void phal_uart_sendByte(phal_uart_Id uartId, U8 byte)
{
	padl_uart_SEND_DATA(UART_FROM_ID(uartId), byte);
}

////////////////////////////////////////////////////////////////
/// Receive byte											 ///
////////////////////////////////////////////////////////////////
U8 phal_uart_receiveByte(phal_uart_Id uartId)
{
	return padl_uart_READ_RECEIVED_DATA(UART_FROM_ID(uartId));
}

////////////////////////////////////////////////////////////////
/// Uart 0 interrupt routine								 ///
////////////////////////////////////////////////////////////////
#if (UART0_ENABLE == TRUE) && (UART0_ENABLE_INTERRUPT == TRUE)
void phal_uart0_interruptRoutine(void)
{
	U8 interruptID;

	interruptID = padl_uart_GET_INTERRUPT_ID(padl_uart_UART0);

	if (interruptID == padl_uart_IIR_RLS)
	{
		if(padl_uart_IS_OVERRUN_ERROR(padl_uart_UART0)
			|| padl_uart_IS_PARITY_ERROR(padl_uart_UART0)
			|| padl_uart_IS_FRAMING_ERROR(padl_uart_UART0)
			|| padl_uart_IS_RX_FIFO_ERROR(padl_uart_UART0)
			|| padl_uart_IS_BREAK_INTERRUPT(padl_uart_UART0))
		{
		  	U8 Dummy = padl_uart_READ_RECEIVED_DATA(padl_uart_UART0);
#if UART0_ENABLE_RECEIVING_DATA_ERROR_INTERRUPT == TRUE
		  	UART0_RECEIVING_DATA_ERROR_HANDLER(UART0_RECEIVING_DATA_ERROR_ARG);
#endif
		}
		else if (padl_uart_IS_RECEIVE_DATA_READY(padl_uart_UART0))
		{
#if UART0_ENABLE_DATA_RECEIVED_INTERRUPT == TRUE
			UART0_DATA_RECEIVED_HANDLER(UART0_DATA_RECEIVED_ARG);
#endif
		}
	}
	else if (interruptID == padl_uart_IIR_RDA)
	{
#if UART0_ENABLE_DATA_RECEIVED_INTERRUPT == TRUE
		UART0_DATA_RECEIVED_HANDLER(UART0_DATA_RECEIVED_ARG);
#endif
	}
	else if (interruptID == padl_uart_IIR_THRE)
	{
		if (padl_uart_IS_TRANSMISSION_READY(padl_uart_UART0))
		{
#if UART0_ENABLE_DATA_TRANSMITTED_INTERRUPT == TRUE
			UART0_DATA_TRANSMITTED_HANDLER(UART0_DATA_TRANSMITTED_ARG);
#endif
		}
	}
}
#endif

////////////////////////////////////////////////////////////////
/// Uart 1 interrupt routine								 ///
////////////////////////////////////////////////////////////////
#if (UART1_ENABLE == TRUE) && (UART1_ENABLE_INTERRUPT == TRUE)
void phal_uart1_interruptRoutine(void)
{
  	U8 interruptID;

	interruptID = padl_uart_GET_INTERRUPT_ID(padl_uart_UART1);

	if (interruptID == padl_uart_IIR_RLS)
	{
		if(padl_uart_IS_OVERRUN_ERROR(padl_uart_UART1)
			|| padl_uart_IS_PARITY_ERROR(padl_uart_UART1)
			|| padl_uart_IS_FRAMING_ERROR(padl_uart_UART1)
			|| padl_uart_IS_RX_FIFO_ERROR(padl_uart_UART1)
			|| padl_uart_IS_BREAK_INTERRUPT(padl_uart_UART1))
		{
		  	U8 Dummy = padl_uart_READ_RECEIVED_DATA(padl_uart_UART1);
#if UART1_ENABLE_RECEIVING_DATA_ERROR_INTERRUPT == TRUE
		  	UART1_RECEIVING_DATA_ERROR_HANDLER(UART1_RECEIVING_DATA_ERROR_ARG);
#endif
		}
		else if (padl_uart_IS_RECEIVE_DATA_READY(padl_uart_UART1))
		{
#if UART1_ENABLE_DATA_RECEIVED_INTERRUPT == TRUE
			UART1_DATA_RECEIVED_HANDLER(UART1_DATA_RECEIVED_ARG);
#endif
		}
	}
	else if (interruptID == padl_uart_IIR_RDA)
	{
#if UART1_ENABLE_DATA_RECEIVED_INTERRUPT == TRUE
		UART1_DATA_RECEIVED_HANDLER(UART1_DATA_RECEIVED_ARG);
#endif
	}
	else if (interruptID == padl_uart_IIR_THRE)
	{
		if (padl_uart_IS_TRANSMISSION_READY(padl_uart_UART1))
		{
#if UART1_ENABLE_DATA_TRANSMITTED_INTERRUPT == TRUE
			UART1_DATA_TRANSMITTED_HANDLER(UART1_DATA_TRANSMITTED_ARG);
#endif
		}
	}

	VICVectAddr = 0;        /* Acknowledge Interrupt */
}
#endif

////////////////////////////////////////////////////////////////
/// Uart 2 interrupt routine								 ///
////////////////////////////////////////////////////////////////
#if (UART2_ENABLE == TRUE) && (UART2_ENABLE_INTERRUPT == TRUE)
void phal_uart2_interruptRoutine(void)
{
	U8 interruptID;

	interruptID = padl_uart_GET_INTERRUPT_ID(padl_uart_UART2);

	if (interruptID == padl_uart_IIR_RLS)
	{
		if(padl_uart_IS_OVERRUN_ERROR(padl_uart_UART2)
			|| padl_uart_IS_PARITY_ERROR(padl_uart_UART2)
			|| padl_uart_IS_FRAMING_ERROR(padl_uart_UART2)
			|| padl_uart_IS_RX_FIFO_ERROR(padl_uart_UART2)
			|| padl_uart_IS_BREAK_INTERRUPT(padl_uart_UART2))
		{
		  	U8 Dummy = padl_uart_READ_RECEIVED_DATA(padl_uart_UART2);
#if UART2_ENABLE_RECEIVING_DATA_ERROR_INTERRUPT == TRUE
		  	UART2_RECEIVING_DATA_ERROR_HANDLER(UART2_RECEIVING_DATA_ERROR_ARG);
#endif
		}
		else if (padl_uart_IS_RECEIVE_DATA_READY(padl_uart_UART2))
		{
#if UART2_ENABLE_DATA_RECEIVED_INTERRUPT == TRUE
			UART2_DATA_RECEIVED_HANDLER(UART2_DATA_RECEIVED_ARG);
#endif
		}
	}
	else if (interruptID == padl_uart_IIR_RDA)
	{
#if UART2_ENABLE_DATA_RECEIVED_INTERRUPT == TRUE
		UART2_DATA_RECEIVED_HANDLER(UART2_DATA_RECEIVED_ARG);
#endif
	}
	else if (interruptID == padl_uart_IIR_THRE)
	{
		if (padl_uart_IS_TRANSMISSION_READY(padl_uart_UART2))
		{
#if UART2_ENABLE_DATA_TRANSMITTED_INTERRUPT == TRUE
			UART2_DATA_TRANSMITTED_HANDLER(UART2_DATA_TRANSMITTED_ARG);
#endif
		}
	}
}
#endif

////////////////////////////////////////////////////////////////
/// Uart 3 interrupt routine								 ///
////////////////////////////////////////////////////////////////
#if (UART3_ENABLE == TRUE) && (UART3_ENABLE_INTERRUPT == TRUE)
void phal_uart3_interruptRoutine(void)
{
	U8 interruptID;

	interruptID = padl_uart_GET_INTERRUPT_ID(padl_uart_UART3);

	if (interruptID == padl_uart_IIR_RLS)
	{
		if(padl_uart_IS_OVERRUN_ERROR(padl_uart_UART3)
			|| padl_uart_IS_PARITY_ERROR(padl_uart_UART3)
			|| padl_uart_IS_FRAMING_ERROR(padl_uart_UART3)
			|| padl_uart_IS_RX_FIFO_ERROR(padl_uart_UART3)
			|| padl_uart_IS_BREAK_INTERRUPT(padl_uart_UART3))
		{
		  	U8 Dummy = padl_uart_READ_RECEIVED_DATA(padl_uart_UART3);
#if UART3_ENABLE_RECEIVING_DATA_ERROR_INTERRUPT == TRUE
		  	UART3_RECEIVING_DATA_ERROR_HANDLER(UART3_RECEIVING_DATA_ERROR_ARG);
#endif
		}
		else if (padl_uart_IS_RECEIVE_DATA_READY(padl_uart_UART3))
		{
#if UART3_ENABLE_DATA_RECEIVED_INTERRUPT == TRUE
			UART3_DATA_RECEIVED_HANDLER(UART3_DATA_RECEIVED_ARG);
#endif
		}
	}
	else if (interruptID == padl_uart_IIR_RDA)
	{
#if UART3_ENABLE_DATA_RECEIVED_INTERRUPT == TRUE
		UART3_DATA_RECEIVED_HANDLER(UART3_DATA_RECEIVED_ARG);
#endif
	}
	else if (interruptID == padl_uart_IIR_THRE)
	{
		if (padl_uart_IS_TRANSMISSION_READY(padl_uart_UART3))
		{
#if UART3_ENABLE_DATA_TRANSMITTED_INTERRUPT == TRUE
			UART3_DATA_TRANSMITTED_HANDLER(UART3_DATA_TRANSMITTED_ARG);
#endif
		}
	}
}
#endif
